﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Text.RegularExpressions;

namespace FictionsDownload.BLL
{
    class HtmlParser
    {
        private string[] htmlcode; //把html转为数组形式用于分析
        private StringBuilder result = new StringBuilder();  //输出的结果
        private int seek; //分析文本时候的指针位置
        private string[] keepTag;  //用于保存要保留的尖括号内容
        private bool _inTag;  //标记现在的指针是不是在尖括号内
        private bool needContent = true;  //是否要提取正文
        private string tagName;  //当前尖括号的名字
        private string[] specialTag = new string[] { "script", "style", "!--" };  //特殊的尖括号内容，一般这些标签的正文是不要的

        /// <summary>
        /// 当指针进入尖括号内，就会触发这个属性。这里主要逻辑是提取尖括号里的标签名字
        /// </summary>
        public bool inTag
        {
            get { return _inTag; }
            set
            {
                _inTag = value;
                if (!value)
                    return;
                tagName = "";
                while (true)
                {
                    //循环读取字符串，到" "或者">"时停止，读取的字符串就是tagName
                    string word = read();
                    if (word != " " && word != ">")
                    {
                        tagName += word;
                    }
                    else if (word == " " && tagName.Length > 0)
                    {
                        break;
                    }
                    else if (word == ">")
                    {
                        inTag = false;
                        seek -= 1;
                        break;
                    }
                }
            }
        }
        /// <summary>
        /// 初始化类，将string Html转成string[];
        /// </summary>
        /// <param name="html">要分析的html代码</param>
        public HtmlParser(string html)
        {
            htmlcode = new string[html.Length];
            for (int i = 0; i < html.Length; i++)
            {
                htmlcode[i] = html[i].ToString();
            }
            KeepTag(new string[] { });
        }
        /// <summary>
        /// 设置要保存那些标签不要被过滤掉
        /// </summary>
        /// <param name="tags"></param>
        public void KeepTag(string[] tags)
        {
            keepTag = tags;
        }
        /// <summary>
        ///  输出处理后的文本
        /// </summary>
        /// <returns></returns>
        public string Text()
            {
                //开始标签位置
                int startTag = 0;
                //结束标签位置
                int endTag = 0;
                while (seek < htmlcode.Length)
                {
                    string word = read().ToLower();
                    if (word == "<")
                    {
                        startTag = seek-1;
                        inTag = true;
                    }
                    else if (word == ">")
                    {
                        //判断是否保存标签
                        endTag = seek-1;
                        inTag = false;
                        if (iskeepTag(tagName.Replace("/", "")))
                        {
                            for (int i = startTag; i == endTag; i++)
                            {
                                result.Append(htmlcode[i].ToString());
                            }
                        }
                        //跳过注释的内容
                        else if (tagName.StartsWith("!--"))
                        {
                            while (true)
                            {
                                if (read() == "-")
                                {
                                    if (read() == "-")
                                    {
                                        if (read() == ">")
                                        {
                                            break;
                                        }
                                        else
                                        {
                                            seek -= 1;
                                        }
                                    }
                                }
                            }
                        }
                        //其他情况:其他要跳过的标签内容
                        else
                        {
                            foreach (string str in specialTag)
                            {
                                if (tagName == str)
                                {
                                    needContent = false;
                                    break;
                                }
                                else
                                {
                                    needContent = true;
                                }
                            }
                        }
                    }
                    else if (!inTag && needContent)
                    {
                        result.Append(word);
                    }

                }
                return result.ToString();
            }
            /// <summary>
            /// 判断是否要保存这个标签
            /// </summary>
            /// <param name="tag"></param>
            /// <returns></returns>
            private bool iskeepTag(string tag)
            {
                foreach (string ta in keepTag)
                {
                    if (tag.ToLower() == ta.ToLower())
                    {
                        return true;
                    }
                }
                return false;
            }
            /// <summary>
            /// 读取当前字符，指针下移
            /// </summary>
            /// <returns></returns>
            private string read()
            {
                return htmlcode[seek++];
            }
        }
    }
